<?php

namespace app\lib;

class FileDB
{
    // 选择表
    public static function table($_table, $_db = 'db01')
    {
        $db = new FileDB($_table, $_db);

        return $db;
    }

    private $table = '';
    public $db_file = '';
    private $head_file = '';
    private $where = [];
    private $info = null;
    private $sort = '';

    // 构造函数
    public function __construct($_table, $_db = 'db01')
    {
        $this->table = $_table;
        if (strpos($_db, '/') === false)
        {
            $this->db_file = './' . $_db . '/' . $_table . '.zdb';
            $this->head_file = './' . $_db . '/' . $_table . '.zdbh';
        }
        else
        {
            $this->db_file = $_db . '/' . $_table . '.zdb';
            $this->head_file = $_db . '/' . $_table . '.zdbh';
        }
        $this->db_file = public_path() . $this->db_file;
        $this->head_file = public_path() . $this->head_file;

        if (!file_exists($this->db_file))
        {
            $this->init();
        }

        // 获取信息
        $content = @file_get_contents($this->head_file);
        $this->info = json_decode($content, true);
    }

    // 初始化
    private function init()
    {
        $content = [
            'version'     => 'v1.0',
            'table'       => $this->table,
            'last_id'     => 0,
            'count'       => 0,
            'create_time' => date('Y-m-d H:i:s'),
            'last_time'   => date('Y-m-d H:i:s'),
        ];
        file_put_contents($this->head_file, json_encode($content));
        file_put_contents($this->db_file, '');
    }

    // 获取信息
    public function info()
    {
        return $this->info;
    }

    // 保存信息
    private function info_save()
    {
        return file_put_contents($this->head_file, json_encode($this->info));
    }

    // 获取列表
    public function select()
    {
        $list = [];

        $handle = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this->parseWhere($buffer);
            if ($item !== null)
            {
                $list[] = $item;
            }
        }
        fclose($handle);

        // 处理排序
        if ($this->sort != '')
        {
            $sort_key = $sort = trim($this->sort);
            $sort_attr = SORT_REGULAR;

            if (strtolower(substr($sort, -5)) == ' desc')
            {
                $sort_attr = $sort_attr|SORT_DESC;
                $sort_key = substr($sort, 0, -5);
            }

            $sort_data = [];

            foreach ($list as $key => $arr)
            {
                $sort_data[$key] = $arr[$sort_key];
            }

            array_multisort($sort_data, $sort_attr, $list);
        }

        return $list;
    }

    public function order($sort)
    {
        $this->sort = $sort;

        return $this;
    }

    // 获取单条值
    public function find($id)
    {
        if (empty($id))
        {
            return null;
        }

        $item = null;

        $id = intval($id);
        $index = 0;
        $handle = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $item = trim($buffer);
                $item = json_decode($item, true);
                break;
            }
        }
        fclose($handle);

        return $item;
    }

    // 条件过滤
    public function where($key, $op, $val = null)
    {
        if ($val === null)
        {
            return $this->where($key, '=', $op);
        }

        $this->where[] = [$key, $op, $val];

        return $this;
    }

    // 解析条件过滤
    public function parseWhere($str)
    {
        $str = trim($str);
        if (empty($str))
        {
            return null;
        }

        $item = json_decode($str, true);

        if ($item === false)
        {
            return null;
        }

        if (!empty($this->where))
        {
            $bo = true;
            foreach ($this->where as $r)
            {
                $k = $r[0];
                $v = $r[2];
                if (!isset($item[$k]))
                {
                    return null;
                }
                switch ($r[1])
                {
                    case '=':
                        if ($item[$k] != $v)
                        {
                            return null;
                        }
                        break;
                    case '>':
                        if ($item[$k] <= $v)
                        {
                            return null;
                        }
                        break;
                    case '<':
                        if ($item[$k] >= $v)
                        {
                            return null;
                        }
                        break;
                    case 'like':
                        if (strpos($item[$k],$v) === false)
                        {
                            return null;
                        }
                        break;
                }
            }
        }

        return $item;
    }

    // 数量限制
    public function selectLimit($start, $length = 0)
    {
        if ($length === 0)
        {
            $length = $start;
            $start = 0;
        }

        if ($length <= 0)
        {
            return [];
        }

        $list = [];

        $index = 0;
        $count = 0;
        $handle = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this->parseWhere($buffer);
            if ($item !== null)
            {
                $index++;
                if ($index > $start)
                {
                    $count++;
                    $list[] = $item;
                }

                if ($count >= $length)
                {
                    break;
                }
            }
        }
        // 处理排序
        if ($this->sort != '')
        {
            $sort_key = $sort = trim($this->sort);
            $sort_attr = SORT_REGULAR;

            if (strtolower(substr($sort, -5)) == ' desc')
            {
                $sort_attr = $sort_attr|SORT_DESC;
                $sort_key = substr($sort, 0, -5);
            }

            $sort_data = [];

            foreach ($list as $key => $arr)
            {
                $sort_data[$key] = $arr[$sort_key];
            }

            array_multisort($sort_data, $sort_attr, $list);
        }
        fclose($handle);

        return $list;
    }

    // 数量查询
    public function count()
    {
        $count = 0;

        $handle = @fopen($this -> db_file, 'r');
        while (($buffer = fgets($handle)) !== false)
        {
            $item = $this->parseWhere($buffer);
            if ($item !== null)
            {
                $count++;
            }
        }
        fclose($handle);

        return $count;
    }

    // 插入单条数据
    public function insert($item)
    {
        $this->info['last_id']++;
        $this->info['count']++;

        $item['id'] = $this->info['last_id'];

        file_put_contents($this->db_file, json_encode($item) . PHP_EOL, FILE_APPEND|LOCK_EX);

        $this->info_save();

        return $item['id'];
    }

    // 批量插入
    public function insertAll($list)
    {
        $content = '';
        foreach ($list as $r)
        {
            $this->info['last_id']++;
            $this->info['count']++;

            $r['id'] = $this->info['last_id'];

            $content .= json_encode($r) . PHP_EOL;
        }

        file_put_contents($this->db_file, $content, FILE_APPEND|LOCK_EX);

        $this->info_save();

        return count($list);
    }

    // 条件更新
    private function updateWhere($update)
    {
        $bo = false;

        $handle_writer = @fopen($this->db_file . 'w', 'w');
        $handle_reader = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $item = $this->parseWhere($buffer);
            if ($item !== null)
            {
                $new = array_merge($item, $update);
                fputs($handle_writer, json_encode($new) . PHP_EOL);
                $bo = true;
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this->db_file . 'w', $this->db_file);
        }
        else
        {
            unlink($this->db_file . 'w');
        }
    }

    // 单条更新
    public function update($item)
    {
        if (!empty($this->where))
        {
            if (isset($item['id']))
            {
                return false;
            }

            $this->updateWhere($item);

            return true;
        }

        if (empty($item['id']))
        {
            return false;
        }

        $bo = false;
        $id = $item['id'];
        $index = 0;
        $handle_writer = @fopen($this->db_file . 'w', 'w');
        $handle_reader = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    $new = array_merge($old, $item);
                    fputs($handle_writer, json_encode($new) . PHP_EOL);
                    $bo = true;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this->db_file . 'w', $this->db_file);
        }
        else
        {
            unlink($this->db_file . 'w');
        }

        return $bo;
    }

    // 批量更新
    public function updateAll($list)
    {
        $arr = array_column($list, null, 'id');

        $count = 0;
        $index = 0;
        $handle_writer = @fopen($this->db_file . 'w', 'w');
        $handle_reader = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if (isset($arr[$index]))
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    $new = array_merge($old, $arr[$index]);
                    fputs($handle_writer, json_encode($new) . PHP_EOL);
                    $count++;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($count > 0)
        {
            rename($this->db_file . 'w', $this->db_file);
        }
        else
        {
            unlink($this->db_file . 'w');
        }

        return $count;
    }

    // 条件删除
    private function deleteWhere()
    {
        $bo = false;

        $handle_writer = @fopen($this->db_file . 'w', 'w');
        $handle_reader = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $item = $this->parseWhere($buffer);
            if ($item !== null)
            {
                fputs($handle_writer, PHP_EOL);
                $bo = true;
                $this->info['count']--;
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this->db_file . 'w', $this->db_file);
            $this->info_save();
        }
        else
        {
            unlink($this->db_file . 'w');
        }
    }

    // 删除
    public function delete($id = null)
    {
        if (!empty($this->where))
        {
            $this->deleteWhere();

            return true;
        }

        if (empty($id))
        {
            return false;
        }

        $bo = false;
        $index = 0;
        $handle_writer = @fopen($this->db_file . 'w', 'w');
        $handle_reader = @fopen($this->db_file, 'r');
        while (($buffer = fgets($handle_reader)) !== false)
        {
            $index++;
            if ($index == $id)
            {
                $old = trim($buffer);
                $old = json_decode($old, true);
                if (!empty($old))
                {
                    fputs($handle_writer, PHP_EOL);
                    $bo = true;
                }
                else
                {
                    fputs($handle_writer, $buffer);
                }
            }
            else
            {
                fputs($handle_writer, $buffer);
            }
        }
        fclose($handle_reader);
        fclose($handle_writer);

        if ($bo)
        {
            rename($this->db_file . 'w', $this->db_file);
            $this->info['count']--;
            $this->info_save();
        }
        else
        {
            unlink($this->db_file . 'w');
        }

        return $bo;
    }

    // 清空表
    public function deleteAll($where = null)
    {
        if ($where === null)
        {
            $this->init();
        }

        return true;
    }
}